package isjinhao.jlox.grammar.statement;

import isjinhao.jlox.grammar.ParseError;
import isjinhao.jlox.grammar.Parser;
import isjinhao.jlox.grammar.code.represention.Block;
import isjinhao.jlox.grammar.expression.represention.Expression;
import isjinhao.jlox.grammar.expression.represention.Identifier;
import isjinhao.jlox.grammar.statement.represention.*;
import isjinhao.jlox.lexical.TokenSequence;
import isjinhao.jlox.lexical.TokenType;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 *  Statement 语法的定义。
 *  grammar:
 *      1、print            ->  "print" expression ";"
 *      2、varDefinition    ->  "var" (IDENTIFIER "=" expression)? ";"
 *      3、assignment       ->  IDENTIFIER "=" expression ";"
 *      4、block            ->  "{" statement* "}"
 *      5、statement        ->  print | varDefinition | assignment | block
 *  e.g.
 *      1、print (1 + 2) * ((4 / 2) / (2 - 1)) * (1.5 + 2.5);
 *      2、{
 *              var name = "ISJINHAO";
 *              name = "浩天帝";
 *              print name;
 *              {
 *                  name = "詹金浩";
 *                  {
 *                      print name;
 *                  }
 *                  print name;
 *              }
 *              print name;
 *         }
 *
 * @Author ISJINHAO
 * @Date 2021/2/21 10:36
 */
public class StatementParser extends Parser<Statement> {

    protected StatementExpressionParser expressionParser;

    public StatementParser(TokenSequence tokenSequence) {
        super(tokenSequence);
        expressionParser = new StatementExpressionParser(tokenSequence);
    }

    @Override
    public Statement parse() {
       return statement();
    }

    protected Statement statement() {
        if (tokenSequence.curEqual(TokenType.LEFT_BRACE)) {
            return block();
        } else if(tokenSequence.curEqual(TokenType.PRINT)) {
            return print();
        } else if(tokenSequence.curEqual(TokenType.VAR)) {
            return varDefinition();
        } else if(tokenSequence.curEqual(TokenType.IDENTIFIER)) {
            return assignment();
        } else if(tokenSequence.curEqual(TokenType.LEFT_BRACE)) {
            return block();
        }
        return null;
    }

    protected Statement print() {
        tokenSequence.advance();
        Expression parse = expressionParser.parse();
        tokenSequence.consume(TokenType.SEMICOLON, "Expect ';' after print statement.");
        return new Print(parse);
    }

    protected Statement varDefinition() {
        tokenSequence.advance();
        Expression identifier = expressionParser.parse();
        if(!(identifier instanceof Identifier)) {
            throw new ParseError("变量定义语句的解析失败");
        }
        Expression initializer = null;
        if (tokenSequence.curEqual(TokenType.EQUAL)) {
            tokenSequence.advance();
            initializer = expressionParser.parse();
        }
        tokenSequence.consume(TokenType.SEMICOLON, "Expect ';' after varDefinition statement.");
        return new VarDefinition(((Identifier) identifier).getName(), initializer);
    }

    protected Statement assignment() {
        Expression identifier = expressionParser.parse();
        if(!(identifier instanceof Identifier)) {
            throw new ParseError("变量定义语句的解析失败");
        }
        tokenSequence.consume(TokenType.EQUAL, "Expect = ");
        Expression expression = expressionParser.parse();
        tokenSequence.consume(TokenType.SEMICOLON, "Expect ';' after assignment statement.");
        return new Assignment(((Identifier) identifier).getName(), expression);
    }

    protected Statement block() {
        tokenSequence.advance();
        List<Statement> statements = new ArrayList<>();
        while (!tokenSequence.curEqual(TokenType.RIGHT_BRACE)) {
            statements.add(statement());
        }
        tokenSequence.consume(TokenType.RIGHT_BRACE, "Expect '}' after block.");
        return new Block(statements);
    }

}